package com.bosssoft.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 项昊天
 * @create 2021/8/20 20:08
 */
@Slf4j
public class JwtTokenUtil {
  private static final String SECRET_KEY = "fiscal_integration";

  private static final long EXPIRATION_TIME = 3600000L * 24*7;

  /**
   * 生成令牌
   *
   * @param username 用户名
   * @return 令牌
   */
  public static String generateToken(String username, Long id) {
    Map<String, Object> claims = new HashMap<>(3);
    claims.put(Claims.SUBJECT, username);
    claims.put(Claims.ISSUED_AT, new Date());
    claims.put(Claims.ID, id);
    return generateToken(claims);
  }

  /**
   * 从令牌中获取用户名
   *
   * @param token 令牌
   * @return 用户名
   */
  public static String getUsernameFromToken(String token) {
    String username = null;
    try {
      Claims claims = getClaimsFromToken(token);
      log.info("claims = {} ", claims.toString());
      username = claims.getSubject();
    } catch (Exception e) {
      log.info("getUsernameFromToken出错 e = ", e.getMessage());
    }
    return username;
  }

  /**
   * 从令牌中获取用户名
   *
   * @param token 令牌
   * @return 用户名
   */
  public static Long getUserIdFromToken(String token) {
    Long id = null;
    try {
      Claims claims = getClaimsFromToken(token);
      log.info("claims = {} ", claims.toString());
      id = Long.parseLong(claims.getId());
    } catch (Exception e) {
      log.info("getUserIdFromToken 出错e = ", e.getMessage());
    }
    return id;
  }

  /**
   * 从令牌中获取用户名
   *
   * @param token 令牌
   * @return 用户名
   */
  public static List<String> getAccessUrlsFromToken(String token) {
    List<String> urls = null;
    try {
      Claims claims = getClaimsFromToken(token);
      log.info("claims = {} ", claims.toString());
      urls = (List<String>) claims.get("accessUrls");
    } catch (Exception e) {
      log.info("getAccessUrlsFromToken 出错e = ", e.getMessage());
    }
    return urls;
  }


  /**
   * 判断令牌是否过期
   *
   * @param token 令牌
   * @return 是否过期
   */
  public static Boolean isTokenExpired(String token) throws  Exception{
    try {
      Claims claims = getClaimsFromToken(token);
      Date expiration = claims.getExpiration();
      return expiration.before(new Date());
    } catch (Exception e) {
      new Throwable(e);
    }
    return true;
  }

  public static Long getTokenExp(String token) throws Exception {
    try {
      Claims claims = getClaimsFromToken(token);
      Date expiration = claims.getExpiration();
      return expiration.getTime() - System.currentTimeMillis();
    } catch (Exception e) {
      new Throwable(e);
    }
    return 0L;
  }
  /**
   * 刷新令牌
   *
   * @param token 原令牌
   * @return 新令牌
   */
  public static String refreshToken(String token) {
    String refreshedToken;
    try {
      Claims claims = getClaimsFromToken(token);
      claims.put(Claims.ISSUED_AT, new Date());
      refreshedToken = generateToken(claims);
    } catch (Exception e) {
      refreshedToken = null;
    }
    return refreshedToken;
  }
  //验证放到网关自定义。
//  /**
//   * 验证令牌
//   *
//   * @param token       令牌
//   * @param userDetails 用户
//   * @return 是否有效
//   */
//  public Boolean validateToken(String token, UserDetails userDetails) throws Exception {
//    AuthUser user = (AuthUser) userDetails;
//    String username = getUsernameFromToken(token);
//    return (username.equals(user.getUsername()) && !isTokenExpired(token));
//  }

  /**
   * 从数据声明生成令牌
   *
   * @param claims 数据声明
   * @return 令牌
   */
  public static String generateToken(Map<String, Object> claims) {
    Date expirationDate = new Date(System.currentTimeMillis()+ EXPIRATION_TIME);
    return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, SECRET_KEY).compact();
  }

  /**
   * 从令牌中获取数据声明
   *
   * @param token 令牌
   * @return 数据声明
   */
  private static Claims getClaimsFromToken(String token) throws Exception {
    Claims claims = null;
    try {
      claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
    } catch (Exception e) {
      new Throwable(e);
    }
    return claims;
  }
}